<?php
namespace library\tencent\wechat\admin_wechat;

use model\WechatSetting;
use think\Db;
use think\Session;

// todo: impl memory cache

class Settings
{
    const ENCODE_NONE = 0;
    const ENCODE_JSON = 1;
    const ENCODE_SERIALIZE = 2;
    const ENCODE_BASE64 = 3;
    const ENCODE_HEX = 4;

    private function __construct() { }


    protected static function model()
    {
        static $m = null;
        if ($m == null) {
            $m=new WechatSetting();
//            $m =model('WechatSetting');
        }
        return $m;
    }


    protected static function normalizeName($name)
    {
        return strtolower($name);
    }


    protected static function predicate($name)
    {
        return static::model()->where(['name' => static::normalizeName($name)]);
    }


    protected static function encode($value, &$encode)
    {
        if ($encode === null) {
            if (is_array($value)) {
                $encode = self::ENCODE_JSON;
            } else if (is_object($value)) {
                $encode = self::ENCODE_SERIALIZE;
            } else {
                $encode = self::ENCODE_NONE;
            }
        }
        switch ($encode) {
            case self::ENCODE_JSON:
                return json_encode($value);
            case self::ENCODE_SERIALIZE:
                return serialize($value);
            case self::ENCODE_BASE64:
                return base64_encode($value);
            case self::ENCODE_HEX:
                return bin2hex($value);
            default:
                return $value;
        }
    }


    protected static function decode($value, $encode)
    {
        switch ($encode) {
            case self::ENCODE_JSON:
                return json_decode($value, true);
            case self::ENCODE_SERIALIZE:
                return unserialize($value);
            case self::ENCODE_BASE64:
                return base64_decode($value);
            case self::ENCODE_HEX:
                return hex2bin($value);
            default:
                return $value;
        }
    }

    public static function exists($name)
    {
        return static::predicate($name)->count() > 0;
    }

    public static function remove($name)
    {
        return static::predicate($name)->delete();
    }

    public  static function clear()
    {
        static::model()->execute('truncate table __SETTING__');
    }


    public static function get($name)
    {
        $entry = static::model()->where(['name'=>static::normalizeName($name)])->find();//todo

        if ($entry) {
            return static::decode($entry['value'], $entry['encode']);
        }
        return null;
    }


    public static function add($name, $value, $encode = null)
    {
        $value = static::encode($value, $encode);
        return static::model()->insert([
            'type'     => 0,
            'encode'   => $encode,
            'category' => 0,
            'name'     => $name,
            'value'    => $value
        ]);
    }


    public static function update($name, $value, $encode = null)
    {
        $value = static::encode($value, $encode);
        return static::predicate($name)->update([
            'encode' => $encode,
            'value'  => $value
        ]);
    }


    public static function set($name, $value, $encode = null)
    {
        if (static::exists($name)) {
            static::update($name, $value, $encode);
            return false;
        } else {
            static::add($name, $value, $encode);
            return true;
        }
    }


    public static function reset()
    {
        static::clear();
    }


    public static function readMergedGroup($name, $prefix, array $default, array &$data)
    {
        $group = (array)static::get($name);
        foreach ((array)$default as $key => $value) {
            $data[$prefix . $key] = isset($group[$key]) ? $group[$key] : $value;
        }
    }


    public static function saveMergedGroup($name, $prefix, array $default, array $data)
    {
        $group = array();
        foreach ((array)$default as $key => $value) {
            $subKey = $prefix . $key;
            $group[$key] = isset($data[$subKey]) ? $data[$subKey] : $value;
        }
        static::set($name, $group);
    }

}